﻿

using SqlSugar;
using System;

using System.Data.SqlClient;
using System.Linq.Expressions;
using Zhaoxi.App.Interfaces;

namespace Zhaoxi.NET6.Services
{
    /// <summary>
    /// 提前定义好SqlSugar的基本操作
    /// </summary>
    public class BaseService : IBaseService
    {
        #region Identity
        protected SqlSugarClient _SqlSugarClient { get; private set; }
        /// <summary>
        /// 构造函数注入
        /// </summary>
        /// <param name="context"></param>
        public BaseService(SqlSugarClient context)
        { 
            _SqlSugarClient = context;
        }
        #endregion Identity

        #region Query
        public T Find<T>(int id) where T : class
        {
            return _SqlSugarClient.Queryable<T>().InSingle(id);
        }

        /// <summary>
        /// 不应该暴露给上端使用者，尽量少用
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        [Obsolete("尽量避免使用，using 带表达式目录树的代替")]
        public ISugarQueryable<T> Set<T>() where T : class
        {
            return _SqlSugarClient.Queryable<T>();
        }

        /// <summary>
        /// 这才是合理的做法，上端给条件，这里查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="funcWhere"></param>
        /// <returns></returns>
        public ISugarQueryable<T> Query<T>(Expression<Func<T, bool>> funcWhere) where T : class
        {
            if (funcWhere == null)
                return _SqlSugarClient.Queryable<T>();
            else
                return _SqlSugarClient.Queryable<T>();
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="funcWhere"></param>
        /// <param name="pageSize"></param>
        /// <param name="pageIndex"></param>
        /// <param name="funcOrderby"></param>
        /// <param name="isAsc"></param>
        /// <returns></returns>
        public PageResult<T> QueryPage<T>(Expression<Func<T, bool>> funcWhere, int pageSize, int pageIndex, Expression<Func<T, object>> funcOrderby, bool isAsc = true) where T : class
        {
            var list = _SqlSugarClient.Queryable<T>();
            if (funcWhere != null)
            {
                list = list.Where(funcWhere);
            }
            list = list.OrderBy(funcOrderby, isAsc ? OrderByType.Asc : OrderByType.Desc);
            int totalCount = 0;
            PageResult<T> result = new PageResult<T>()
            {
                DataList = list.ToPageList(pageIndex, pageSize, ref totalCount),
                PageIndex = pageIndex,
                PageSize = pageSize,
                TotalCount = totalCount
            };
            return result;
        }


        #endregion

        #region Insert
        /// <summary>
        /// 即使保存  不需要再Commit
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public T Insert<T>(T t) where T : class, new()
        {
            return _SqlSugarClient.Insertable<T>(t).ExecuteReturnEntity();
        }

        /// <summary>
        /// 批量保存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tList"></param>
        /// <returns></returns>
        public IEnumerable<T> Insert<T>(List<T> tList) where T : class, new()
        {
            _SqlSugarClient.Fastest<T>().PageSize(100000).BulkCopy(tList);
            return tList;
        }
        #endregion

        #region Update
        /// <summary>
        /// 是没有实现查询，直接更新的,需要Attach和State
        /// 
        /// 如果是已经在context，只能再封装一个(在具体的service)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        public bool Update<T>(T t) where T : class, new()
    
        {
            if (t == null) throw new Exception("t is null");
            _SqlSugarClient.Tracking<T>(t);//创建跟踪 
            return _SqlSugarClient.Updateable(t).ExecuteCommandHasChange();
        }


        /// <summary>
        /// 批量修改
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tList"></param>
        /// <returns></returns>
        public bool Update<T>(List<T> tList) where T : class, new()
        {
            _SqlSugarClient.Tracking<T>(tList);//创建跟踪
            return _SqlSugarClient.Updateable<T>(tList).ExecuteCommandHasChange();
        }

        #endregion

        #region Delete

        /// <summary>
        /// 主键删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Id"></param>
        /// <returns></returns>
        public bool Delete<T>(int Id) where T : class, new()
        {
            return _SqlSugarClient.Deleteable<T>().In(Id).ExecuteCommandHasChange();
        }

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public bool Delete<T>(T t) where T : class, new()
        {
            if (t == null) throw new Exception("t is null");
            return _SqlSugarClient.Deleteable<T>(t).ExecuteCommandHasChange();
        }

        /// <summary>
        ///批量删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tList"></param>
        /// <returns></returns>
        public bool Delete<T>(List<T> tList) where T : class, new()
        {
            return _SqlSugarClient.Deleteable<T>(tList).ExecuteCommandHasChange(); //批量删除
        }
        #endregion

        #region Other
        public void Commit()
        {
            _SqlSugarClient.CommitTran();
        }

        public List<T> ExcuteQuery<T>(string sql, SugarParameter[] parameters) where T : class
        {
            return _SqlSugarClient.Ado.SqlQuery<T>(sql, parameters);
        }

        /// <summary>
        /// 执行Sql语句返回受影响的行数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int Excute<T>(string sql, SugarParameter[] parameters) where T : class
        {
            return _SqlSugarClient.Ado.ExecuteCommand(sql, parameters);
        }

        public virtual void Dispose()
        {
            if (_SqlSugarClient != null)
            {
                _SqlSugarClient.Dispose();
            }
        }
        #endregion
    }
}
